Function: RovingTabIndex(objectKeyValueMap) Description: Creates a configurable RovingTabIndex object that will automatically configure accessible keyboard support for associated elements, which will provide one tab stop and manage focus between them using the arrow keys and other common keystrokes. Returns: RTI Instance Object. Requires module: "RovingTabIndex" Note: The first parameter must include a configuration key value map. Though RovingTabIndex will work on any collection of associated DOM elements, it is vitally important to ensure that ARIA widget constructs are correctly referenced when setting up this functionality. To do so correctly in accordance with the ARIA specification, all child element ARIA widget roles must only be included within the focusable elements that are meant to be actionable. Additionally, wen setting the nodes property within the RovingTabIndex setup, the referenced array must only include focusable elements that already possess the correct ARIA child roles for that widget type. The RovingTabIndex() function does not support chaining. Configuration { // Required: DOM node container element for associated child nodes. container: domContainerElement, // Required: Array of child DOM elements that are meant to be focusable. // Important: If referencing the children of an ARIA widget, the array must contain child elements that include the correct role attribute value for that widget. nodes: domElementArray, // Orientation: 0 = both, 1 = horizontal, 2 = vertical. // Default if not specified: 0 orientation: 0, // Auto configure orientation using dynamic switching based on the visual layout of focusable elements. // "off"=Inactive, "semi"=Switches between vertical and horizontal only, "full"= Switches between vertical, horizontal, and both when line-wrapping is detected. autoSwitch: "off", // Starting index to make focusable after instantiation. // Matches starting index to the nodes array, where 0 references the first element. // Default if not specified: 0 startIndex: 0, // Triggering element: The focusable DOM element that triggered this RTI instance if applicable. trigger: domElement, // Parent RTI instance // When set, enables automatic parent/child RTI instance tracking through the event handlers. // Default if not specified: null parent: null, // Enable auto looping // When true, automatically loops forwards and backwards when the arrow keys are used to navigate. // Default if not set: false autoLoop: false, // Optional breakpoints for setting the boundaries of navigable constructs. // May be used to set constricted horizontal or vertical breakpoints, or both at the same time for grids. breakPoint: { // Horizontal // When set to 1 or greater, represents the number of horizontal moves available within the construct, such as columns in a row. // May be combined with orientation to further restrict navigation if needed. // Default if not specified: 0 (disabled) horizontal: 0, // Vertical // When set to 1 or greater, represents the number of vertical moves available within the construct, such as rows in a grid. // May be combined with orientation to further restrict navigation if needed. // Default if not specified: 0 (disabled) vertical: 0, // Set hard stop at horizontal breakpoint // When set to true, prevents further movement beyond the specified breakpoint when the left/right arrow keys are used to navigate. // Default if not specified: false (no stop) horizontalStop: false, // Set hard stop at vertical breakpoint // When set to true, prevents further movement beyond the specified breakpoint when the up/down arrow keys are used to navigate. // Default if not specified: false (no stop) verticalStop: false }, // Optionally set a DC object instance to be associated with this RTI object instance. // Default if not set: null DC: null, // Optional event handlers onClick: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onTouchStart: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onFocus: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onTab: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftTab: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onEnter: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlEnter: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftEnter: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftEnter: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onSpace: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlSpace: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftSpace: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftSpace: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onLeft: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlLeft: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftLeft: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftLeft: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onArrow: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onRight: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlRight: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftRight: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftRight: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onEnd: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlEnd: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftEnd: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftEnd: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onHome: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlHome: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftHome: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftHome: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onEsc: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onDelete: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlDelete: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftDelete: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftDelete: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onPageUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onAltPageUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlPageUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftPageUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftPageUp: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onPageDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onAltPageDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlPageDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onShiftPageDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, onCtrlShiftPageDown: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) {}, // Special event handlers onOpen: function(event, triggerNode, currentRTI, childDC, arrowKeyCode) { // Activates when clicked, or when Enter is pressed on triggerNode. // Also when down-arrow is pressed on a horizontal construct, and when right-arrow is pressed on a vertical construct. (Used for configuring ARIA menus and trees.) }, onClose: function(event, triggerNode, currentRTI, childDC, arrowKeyCode) { // Activates when Escape is pressed on triggerNode. // Also when up-arrow is pressed on a horizontal construct, and when left-arrow is pressed on a vertical construct. (Used for configuring ARIA menus and trees.) }, onTop: function(event, triggerNode, currentRTI, childDC, arrowKeyCode) { // Activates when the beginning boundary is fired while using the Left or Up arrow keys to navigate. }, onBottom: function(event, triggerNode, currentRTI, childDC, arrowKeyCode) { // Activates when the ending boundary is fired while using the Right or Down arrow keys to navigate. }, onBounds: function(event, triggerNode, currentRTI, keyCode) { // Activates when the breakPoint boundary is fired while using the arrow keys to navigate. // keyCode matches the event.which value for the pressed key. (Used for configuring ARIA grids.) // 37 = LeftArrow, 38 = UpArrow, 39 = RightArrow, 40 = DownArrow }, onSelectAll: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { // Activates when Ctrl+A is pressed on the keyboard. }, onCopy: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { // Activates when Ctrl+C is pressed on the keyboard. }, onCut: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { // Activates when Ctrl+X is pressed on the keyboard. }, onPaste: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { // Activates when Ctrl+V is pressed on the keyboard. } } RTI Properties and Methods The following properties and methods are available after an RTI object instance is created. Properties // The DOM node specified as the parent container element. (Matches that specified within the configuration key value map.) // Object type: domElement RTI.container // The array of DOM nodes that are meant to be focusable. (Matches those specified within the configuration key value map.) // If changed programmatically, the RTI.on() method must be called to reassociate the new node list with required event bindings. // Object type: Array RTI.nodes // Current value set as the keyboard navigation orientation. (Matches that specified within the configuration key value map.) // 0 = both horizontal and vertical, 1 = horizontal, and 2 = vertical. // Object type: Number RTI.orientation // Index value of the currently active focusable element within the RTI.nodes array. // Uses array syntax where 0 = the first node in the array. // Do not use this property to change the active node, but instead use the RTI.activate() or RTI.focus() methods for this purpose. // Object type: Number RTI.index // The parent RTI instance associated with the current RTI object instance. (Matches that specified within the configuration key value map.) // Object type: RTI object instance RTI.parent // Map of child RTI objects that are bound to specific triggering elements within the RTI.nodes array. // The triggering element is the key for retreiving the associated child RTI object instance. // This is automatically configured when 1 or more RTI instances are bound using the parent property within the configuration key value map during setup. // Object type: Map object RTI.children // The triggering element that is specified as the controller for the current RTI object instance. (Matches that specified within the configuration key value map.) // If the triggering element is included within the RTI.nodes array of a parent RTI instance, the parent child mappings will be set automatically. // Object type: domElement RTI.trigger // The current setting of automatic loop functionality. (Matches that specified within the configuration key value map.) // Object type: Boolean RTI.autoLoop // The DC object instance associated with the current RTI object instance if applicable. (Matches that specified within the configuration key value map.) // Object type: DC object instance RTI.dc Methods // Activate the specified element within the RTI.nodes array and set this as the currently focusable element. // The first parameter must contain a valid index value, or a domElement reference that already exists within the RTI.nodes array. // This method will set focusability for the specified element, but will not move focus directly. // Returns: RTI object instance RTI.activate(requiredIndexValueOrElementNode) // Activate and move focus to the specified element within the RTI.nodes array and set this as the current element. // The first parameter may optionally contain a valid index value, or a domElement reference that already exists within the RTI.nodes array. // If no parameter is specified, the currently active element within the RTI object instance will receive focus instead. // Returns: RTI object instance RTI.focus(optionalIndexValueOrElementNode) // Remove all RTI event bindings. // This will not destroy the RTI object, but will instead remove all of the RTI related event bindings from all elements within the RTI.nodes array. // Returns: RTI object instance RTI.off() // Recreate all RTI event bindings. // This will not create a new RTI instance, but will instead rebuild all of the RTI related event bindings for all elements within the RTI.nodes array. // Returns: RTI object instance RTI.on() Example: $A.import("RovingTabIndex", { defer: true }, function() { var myRTI = new $A.RovingTabIndex({ container: $A.getElement("tabListId"), // Get parent with role="tablist" // Get children with role="tab" nodes: $A.query('#tabListId *[role="tab"]'), orientation: 1, autoSwitch: "full", autoLoop: true, onClick: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { // Open the specified tab when clicked. }, onEnter: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { myRTI.onClick.call(this, event, triggerNode, currentRTI, childDC); }, onSpace: function(event, triggerNode, currentRTI, childDC, arrowKeyCode, isTop, isBottom) { myRTI.onClick.call(this, event, triggerNode, currentRTI, childDC); }, }); });